﻿using System.ServiceModel;
using gixoom.Dom.Block;
using gixoom.Dom.Storage.Block;

namespace gixoom.Target.WcfWsHttp
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    internal class TargetBlockStorage: ITargetBlockStorage
    {
        private IBlockFacade blockFacade;
        private IBlockStorage blockStorage;

        public TargetBlockStorage(IBlockFacade blockFacade, IBlockStorage blockStorage)
        {
            Ensure.ArgumentNotNull(blockFacade, "blockFacade");
            Ensure.ArgumentNotNull(blockStorage, "blockStorage");

            this.blockFacade = blockFacade;
            this.blockStorage = blockStorage;
        }

        /// <summary>
        /// Stores the specified block in the storage.
        /// </summary>
        /// <param name="blockBytes">the block bytes</param>
        /// <returns>true if the block was successfully stored.</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockBytes</i> is a null reference.</exception>
        public bool StoreBlock(byte[] blockBytes)
        {
            Ensure.ArgumentNotNull(blockBytes, "blockBytes");

            // TODO: ArgumentException should be processed somehow
            IBlock block = blockFacade.CreateBlockFromBytes(blockBytes);
            bool result = (block != null) && blockStorage.StoreBlock(block);

            return result;
        }

        /// <summary>
        /// Retrieves block content by the specified array which represents the block id.
        /// </summary>
        /// <param name="blockId">the byte array which represents the block id</param>
        /// <returns>the content of the block by the specified block id or null if the block content
        /// cannot be retrieved</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockIdBytes</i> is a null reference.</exception>
        public byte[] RetrieveBlockContent(byte[] blockIdBytes)
        {
            Ensure.ArgumentNotNull(blockIdBytes, "blockIdBytes");

            // TODO: ArgumentException should be processed somehow
            var blockId = blockFacade.CreateBlockIdFromBytes(blockIdBytes);
            var block = blockStorage.RetrieveBlock(blockId);

            byte[] content = (block == null) ?
                (byte[])null : block.GetContentCopy();

            return content;
        }

        /// <summary>
        /// Checks whether the block with the specified block id exists.
        /// </summary>
        /// <param name="blockIdBytes">the block id to check existence of the block for</param>
        /// <returns>true if the block exists</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockIdBytes</i> is a null reference.</exception>
        public bool ExistsBlock(byte[] blockIdBytes)
        {
            Ensure.ArgumentNotNull(blockIdBytes, "blockIdBytes");

            // TODO: ArgumentException should be processed somehow
            var blockId = blockFacade.CreateBlockIdFromBytes(blockIdBytes);
            bool exists = blockStorage.ExistsBlock(blockId);

            return exists;
        }
    }
}
